/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package simulador;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JLabel;

/**
 *
 * @author rangel
 */
public class Bot {

	static int maxPower = 8;
	static int minPower = -8;
	public float xPosition = 0,  yPosition = 0; // Preciso disso :X
	private int width,  height;
	private Goal goal;
	private float xVector = 0,  yVector = 0;
	private float xPower = 0,  yPower = 0;
	private String type;
	private float repulsionRadius = 100;
	private float repulsionForceX = 0;
	private float repulsionForceY = 0;
	static Color colorBot = Color.blue;
	static Color colorObstacle = Color.green;
	static float k_repulsive = 250.0f;
	static float k_atractive_goal = 2;
	private boolean atraction = true;
	private Scenario scenario;
	private int count = 0;
	private int vida;
	public java.util.List<Atom> path;
	private JLabel image = new JLabel();
	private String imagePath;
	private AStar astar = new AStar();
	private boolean buscandoSangue = false;
	private int buscouSangue = 0;

	public void setAtraction(boolean atraction) {
		this.atraction = atraction;
	}

	public void setBestPath(java.util.List<Atom> p) {
		path = p;
	}

	public void setVida(int v) {
		vida = v;
	}

	public int getVida() {
		return vida;
	}

	public boolean morreu(ArrayList<Torre> listTorres) {
		int i, j;
		for (i = 0; listTorres!=null && i < listTorres.size(); i++) {
			Torre torre = listTorres.get(i);
			ArrayList<Bot> tiros = torre.getListTiros();
			for (j = 0; j < tiros.size(); j++) {
				Bot tiro = tiros.get(j);
				if ((int)(tiro.xPosition/scenario.cellSpace) == (int)(xPosition/scenario.cellSpace) && (int)(tiro.yPosition/scenario.cellSpace) == (int)(yPosition/scenario.cellSpace)) {
					setVida(getVida() - 10);
					tiro.removeLabel();
					tiros.remove(j);
				}
			}
		}
		if (getVida() <= 0) {
			return true;
		}
		return false;
	}

	public float getRadius() {
		return width / 2;
	}

	public Bot(Point position, int width, int height, String type, boolean atractionGoal, Scenario scenario) {
		xPosition = position.x;
		yPosition = position.y;
		this.height = height;
		this.width = width;
		this.type = type;
		xPower = yPower = 0;
		repulsionRadius += width;
		atraction = atractionGoal;
		this.scenario = scenario;
		path = new ArrayList<Atom>();
		//image.setBounds((int)xPosition, (int)yPosition, 100, 100);
		//scenario.add(image);
	}

	// Bot discreto
	public Bot(Point position, int width, int height, String type, boolean atractionGoal, Scenario scenario, int vida, String icon) {
		xPosition = position.x;
		yPosition = position.y;
		this.height = height;
		this.width = width;
		this.type = type;
		xPower = yPower = 0;
		repulsionRadius += width;
		atraction = atractionGoal;
		this.scenario = scenario;
		path = new ArrayList<Atom>();
		this.vida = vida;
		imagePath = icon;
		image.setIcon(new javax.swing.ImageIcon(getClass().getResource(icon)));
		image.setBounds((int)xPosition-scenario.cellSpace/2, (int)yPosition-scenario.cellSpace/2, scenario.cellSpace, scenario.cellSpace);
		image.setVerticalAlignment(image.TOP);
		image.setHorizontalAlignment(image.LEFT);
		scenario.add(image);
	}

	public void removeLabel()
	{
		scenario.remove(image);
	}

	public void randomMotion() {
		int result = (int) (Math.random() * 100) % 2;
		// Decide se vai aplicar alguma forca
		if (result == 1 && count == 0) {
			count = 200;
			// Decide direcao da forca
			int signal = 1;
			if ((int) (Math.random() * 100) % 2 == 1) {
				signal = -1;
			}
			xPower = (float) Math.random() * signal;
			yPower = (float) Math.random() * signal;
		} else {
			count = (count == 0) ? 0 : (count - 1);
			if (count == 0) {
				xPower = yPower = 0;
			}
		}
	}

	public boolean crumbsFound() {
		// Pesquisa na lista de migalhas do agent para ver se alguma está na visão do Bot
		for (int i = 0; goal != null && i < goal.getBreadCrumbs().size(); i++) {
			Point p = goal.getBreadCrumbs().get(i);
			double dist = Math.sqrt((xPosition - p.x) * (xPosition - p.x) + (yPosition - p.y) * (yPosition - p.y));
			if (dist <= repulsionRadius / 2) {
				return true;
			}
		}
		return false;
	}

	public void addGoal(Goal goal) {
		this.goal = goal;
		if (!atraction) {
			if (crumbsFound()) {
				atraction = true;
			} else {
				atraction = false;
				randomMotion();
			}

		} else if (goal != null) {
			xVector = goal.getXPosition() - xPosition;
			yVector = goal.getYPosition() - yPosition;
			float max = Math.max(Math.abs(xVector), Math.abs(yVector));
			if (max > 0) {
				xPower = k_atractive_goal * (float) (xVector / max);
				yPower = k_atractive_goal * (float) (yVector / max);
			}
		}
	}

	public float distance(Bot b) {
		float x = b.xPosition - xPosition;
		float y = b.yPosition - yPosition;
		return (float) Math.sqrt(x * x + y * y) - width / 2 - b.width / 2;
	}

	public void updateRepulseForces(Bot b) {
		float dist = distance(b);
		if (dist <= repulsionRadius && dist > 2) {
			float force = k_repulsive / (dist * dist);
			float cos = (xPosition - b.xPosition) / dist;
			float sin = (yPosition - b.yPosition) / dist;
			repulsionForceX += force * cos;
			repulsionForceY += force * sin;
			b.repulsionForceX -= force * cos;
			b.repulsionForceY -= force * sin;
		}
	}

	public void updateRepulseForces(float[] vet) {
		repulsionForceX += vet[0];
		repulsionForceY += vet[1];
	}

	public void draw(Graphics2D g2d, boolean radar) {
		if (type.equals("obstacle")) {
			g2d.setColor(colorObstacle);
		} else if (type.equals("bot")) {
			g2d.setColor(colorBot);
			if (radar) {
				g2d.drawOval((int) Math.round(xPosition - (repulsionRadius) / 2), (int) Math.round(yPosition - (repulsionRadius) / 2), (int) Math.round(repulsionRadius), (int) Math.round(repulsionRadius));
			}
		}

		g2d.fillOval((int) Math.round(xPosition - width / 2), (int) Math.round(yPosition - height / 2), width, height);

		g2d.setColor(Color.black);
		g2d.setStroke(new BasicStroke(2.0f));
		g2d.drawOval((int) Math.round(xPosition - width / 2), (int) Math.round(yPosition - height / 2), width, height);
		g2d.setStroke(new BasicStroke(1.0f));
	}

	public void drawImage(Graphics2D g2d, String image, int x, int y) {

		
		BufferedImage img = null;
		try {
			img = ImageIO.read(new File(image));
		} catch (IOException ex) {
			Logger.getLogger(Scenario.class.getName()).log(Level.SEVERE, null, ex);
		}
		AffineTransform origXform = g2d.getTransform();
		AffineTransform newXform = (AffineTransform) (origXform.clone());

//		newXform.rotate(Math.toRadians(rotate), xRot, yRot);
		g2d.setTransform(newXform);

		g2d.drawImage(img, x, y, null);
		g2d.setTransform(origXform); // Volta o eixo ao estado original
	}

	public void updateAtractive(float atractive) {
		yPower *= atractive;
		xPower *= atractive;
	}

	public void updatePosition() {
		xPosition += xPower + repulsionForceX;
		yPosition += yPower + repulsionForceY;

		// Limites da tela
		if ((xPosition + width / 2) < 0) {
			xPosition = scenario.getWidth() + width / 2;
		//yPosition = scenario.getHeight() - yPosition;
		} else if ((xPosition - width / 2) > scenario.getWidth()) {
			xPosition = -width / 2;
		//yPosition = scenario.getHeight() - yPosition;
		}
		if ((yPosition + width / 2) < 0) {
			yPosition = scenario.getHeight() + width / 2;
		} else if ((yPosition - width / 2) > scenario.getHeight()) {
			yPosition = -width / 2;
		}

		image.setBounds((int)xPosition, (int)yPosition, 100, 100);


		repulsionForceX = repulsionForceY = 0;
	}

	public void move(float x, float y) {
		xPosition = x;
		yPosition = y;
		image.setBounds((int)xPosition-scenario.cellSpace/2, (int)yPosition-scenario.cellSpace/2, scenario.cellSpace, scenario.cellSpace);
		astar.setScenario(scenario);
		if(buscouSangue!=0 && buscouSangue%3==0)
		{
			for(int i = 0; i< 5; i++)
				randomMotion();
			return;
		}
		if(scenario.heartPosition!=null && !buscandoSangue && getVida()<=50)
		{
			if(path.size()<getVida()/10)
				return;
			buscandoSangue = true;
			astar.setGoal(scenario.heartPosition.x/scenario.cellSpace, scenario.heartPosition.y/scenario.cellSpace);
			astar.setCurrentPos((int) (xPosition / scenario.cellSpace), (int) (yPosition / scenario.cellSpace));
			if(xPosition>=scenario.heartPosition.x)
				changeImage("/images/Tartaruga-avoadoreE.gif");
			else
				changeImage("/images/Tartaruga-avoadoreD.gif");
			setBestPath(astar.bestPath());
			return;
		}
	}

	void changeImage(String icon) {
		image.setIcon(new javax.swing.ImageIcon(getClass().getResource(icon)));
		imagePath = icon;
	}

	String getImagePath() {
		return imagePath;
	}

	public void incBuscouSangue()
	{
		buscouSangue++;
	}

	public boolean getBuscandoSangue() {
		return buscandoSangue;
	}

	public void setBuscandoSangue(boolean b) {
		buscandoSangue = b;
	}
}

